<template>
  <div class="mobile-uploader">
    <!-- 快速拍照/录像按钮 -->
    <div v-if="showCameraActions" class="camera-actions">
      <button class="camera-btn photo" @click="takePhoto">
        <div class="camera-icon">
          <tiny-icon-camera />
        </div>
        <span>拍照</span>
      </button>
      <button class="camera-btn video" @click="recordVideo">
        <div class="camera-icon">
          <tiny-icon-video />
        </div>
        <span>录像</span>
      </button>
      <button class="camera-btn gallery" @click="selectFromGallery">
        <div class="camera-icon">
          <tiny-icon-image />
        </div>
        <span>相册</span>
      </button>
    </div>

    <!-- 拖拽上传区域 -->
    <div
      :class="{
        'drag-over': isDragOver,
        'compact': compact
      }"
      class="upload-zone"
      @click="selectFiles"
      @dragleave="handleDragLeave"
      @drop="handleDrop"
      @dragover.prevent="handleDragOver"
    >
      <div class="upload-content">
        <div class="upload-icon">
          <tiny-icon-cloud-upload v-if="!compact" />
          <tiny-icon-plus v-else />
        </div>
        <div class="upload-text">
          <div class="primary-text">
            {{ compact ? '添加文件' : '点击或拖拽文件到此处' }}
          </div>
          <div v-if="!compact" class="secondary-text">
            支持图片、视频、音频等格式
          </div>
        </div>
      </div>

      <input
        ref="fileInput"
        :accept="accept"
        class="file-input"
        multiple
        type="file"
        @change="handleFileSelect"
      />
    </div>

    <!-- 上传选项 -->
    <div v-if="showOptions && !compact" class="upload-options">
      <div class="option-row">
        <div class="option-item">
          <label>上传到</label>
          <tiny-select v-model="uploadSettings.albumId" placeholder="选择相册">
            <tiny-option
              v-for="album in albums"
              :key="album.id"
              :label="album.name"
              :value="album.id"
            />
          </tiny-select>
        </div>
      </div>

      <div class="option-row">
        <div class="option-item full-width">
          <label>标签</label>
          <tiny-input
            v-model="uploadSettings.tags"
            placeholder="添加标签，用逗号分隔"
          />
        </div>
      </div>

      <div class="option-row">
        <tiny-checkbox v-model="uploadSettings.enableAI">
          启用AI智能识别
        </tiny-checkbox>
        <tiny-checkbox v-model="uploadSettings.enableGPS">
          记录位置信息
        </tiny-checkbox>
      </div>
    </div>

    <!-- 上传队列 -->
    <div v-if="uploadQueue.length > 0" class="upload-queue">
      <div class="queue-header">
        <h4>上传队列 ({{ uploadQueue.length }})</h4>
        <div class="queue-actions">
          <button
            :disabled="isUploading"
            class="queue-btn"
            @click="startUpload"
          >
            <tiny-loading v-if="isUploading" size="small" />
            <tiny-icon-upload v-else />
            {{ isUploading ? '上传中...' : '开始上传' }}
          </button>
          <button class="queue-btn secondary" @click="clearQueue">
            <tiny-icon-delete />
            清空
          </button>
        </div>
      </div>

      <div class="queue-list">
        <div
          v-for="(item, index) in uploadQueue"
          :key="index"
          :class="item.status"
          class="queue-item"
        >
          <!-- 文件预览 -->
          <div class="file-preview">
            <img
              v-if="item.preview && item.type === 'image'"
              :alt="item.name"
              :src="item.preview"
              class="preview-image"
            />
            <div v-else :class="item.type" class="file-icon">
              <component :is="getFileIcon(item.type)" />
            </div>
          </div>

          <!-- 文件信息 -->
          <div class="file-info">
            <div class="file-name">{{ item.name }}</div>
            <div class="file-meta">
              <span class="file-size">{{ formatFileSize(item.size) }}</span>
              <span class="file-type">{{ item.file.type }}</span>
            </div>

            <!-- 上传进度 -->
            <div v-if="item.status === 'uploading' || item.status === 'completed'" class="upload-progress">
              <div class="progress-bar">
                <div
                  :style="{ width: item.progress + '%' }"
                  class="progress-fill"
                ></div>
              </div>
              <span class="progress-text">
                {{ item.status === 'completed' ? '上传完成' : item.progress + '%' }}
              </span>
            </div>

            <!-- 错误信息 -->
            <div v-if="item.status === 'error'" class="error-message">
              {{ item.error }}
            </div>
          </div>

          <!-- 操作按钮 -->
          <div class="file-actions">
            <button
              v-if="item.status === 'pending'"
              class="action-btn remove"
              @click="removeFromQueue(index)"
            >
              <tiny-icon-close />
            </button>
            <button
              v-else-if="item.status === 'error'"
              class="action-btn retry"
              @click="retryUpload(index)"
            >
              <tiny-icon-refresh />
            </button>
            <div v-else-if="item.status === 'completed'" class="success-icon">
              <tiny-icon-check />
            </div>
          </div>
        </div>
      </div>

      <!-- 总体进度 -->
      <div v-if="isUploading" class="overall-progress">
        <div class="progress-info">
          <span>总进度: {{ overallProgress }}%</span>
          <span>{{ completedCount }}/{{ uploadQueue.length }}</span>
        </div>
        <div class="progress-bar">
          <div
            :style="{ width: overallProgress + '%' }"
            class="progress-fill"
          ></div>
        </div>
      </div>
    </div>

    <!-- 相机模态框 -->
    <transition name="modal">
      <div v-if="cameraModalVisible" class="camera-modal" @click="closeCameraModal">
        <div class="camera-container" @click.stop>
          <div class="camera-header">
            <h3>{{ cameraMode === 'photo' ? '拍照' : '录像' }}</h3>
            <button class="close-btn" @click="closeCameraModal">
              <tiny-icon-close />
            </button>
          </div>

          <div class="camera-viewport">
            <video
              ref="cameraVideo"
              autoplay
              class="camera-stream"
              muted
              playsinline
            ></video>

            <canvas
              ref="cameraCanvas"
              class="camera-canvas"
              style="display: none;"
            ></canvas>
          </div>

          <div class="camera-controls">
            <button v-if="cameras.length > 1" class="control-btn" @click="switchCamera">
              <tiny-icon-refresh />
            </button>

            <button
              :class="{ recording: isRecording }"
              class="capture-btn"
              @click="captureMedia"
            >
              <div class="capture-inner"></div>
            </button>

            <button v-if="hasFlash" class="control-btn" @click="toggleFlash">
              <tiny-icon-flash :class="{ active: flashEnabled }" />
            </button>
          </div>
        </div>
      </div>
    </transition>

    <!-- 位置权限请求 -->
    <transition name="toast">
      <div v-if="showLocationPrompt" class="location-prompt">
        <div class="prompt-content">
          <tiny-icon-location />
          <span>是否允许获取位置信息？</span>
        </div>
        <div class="prompt-actions">
          <button @click="denyLocation">拒绝</button>
          <button class="primary" @click="allowLocation">允许</button>
        </div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
import { TinyMessage as Message } from '@opentiny/vue'

// Props
interface Props {
  accept?: string
  multiple?: boolean
  compact?: boolean
  showCameraActions?: boolean
  showOptions?: boolean
  maxFileSize?: number
  maxFiles?: number
  albums?: Array<{ id: string; name: string }>
}

const props = withDefaults(defineProps<Props>(), {
  accept: 'image/*,video/*,audio/*',
  multiple: true,
  compact: false,
  showCameraActions: true,
  showOptions: true,
  maxFileSize: 100 * 1024 * 1024, // 100MB
  maxFiles: 50,
  albums: () => []
})

// Emits
const emit = defineEmits<{
  'files-added': [files: File[]]
  'upload-start': []
  'upload-progress': [progress: number]
  'upload-complete': [results: any[]]
  'upload-error': [error: string]
}>()

// 响应式数据
const fileInput = ref<HTMLInputElement>()
const cameraVideo = ref<HTMLVideoElement>()
const cameraCanvas = ref<HTMLCanvasElement>()
const isDragOver = ref(false)
const isUploading = ref(false)
const cameraModalVisible = ref(false)
const cameraMode = ref<'photo' | 'video'>('photo')
const isRecording = ref(false)
const recordingStartTime = ref(0)
const mediaRecorder = ref<MediaRecorder | null>(null)
const recordedChunks = ref<Blob[]>([])
const showLocationPrompt = ref(false)
const cameras = ref<MediaDeviceInfo[]>([])
const currentCameraIndex = ref(0)
const hasFlash = ref(false)
const flashEnabled = ref(false)
const cameraStream = ref<MediaStream | null>(null)

// 上传设置
const uploadSettings = reactive({
  albumId: '',
  tags: '',
  enableAI: true,
  enableGPS: false,
  quality: 0.8
})

// 上传队列
const uploadQueue = ref<Array<{
  file: File
  name: string
  size: number
  type: string
  preview?: string
  status: 'pending' | 'uploading' | 'completed' | 'error'
  progress: number
  error?: string
}>>([])

// 计算属性
const overallProgress = computed(() => {
  if (uploadQueue.value.length === 0) return 0
  const totalProgress = uploadQueue.value.reduce((sum, item) => sum + item.progress, 0)
  return Math.round(totalProgress / uploadQueue.value.length)
})

const completedCount = computed(() => {
  return uploadQueue.value.filter(item => item.status === 'completed').length
})

// 方法
const selectFiles = () => {
  fileInput.value?.click()
}

const handleFileSelect = (event: Event) => {
  const input = event.target as HTMLInputElement
  const files = Array.from(input.files || [])
  addFilesToQueue(files)
  input.value = '' // 清空输入，允许重复选择同一文件
}

const handleDrop = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = false

  const files = Array.from(event.dataTransfer?.files || [])
  addFilesToQueue(files)
}

const handleDragOver = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = true
}

const handleDragLeave = () => {
  isDragOver.value = false
}

const addFilesToQueue = (files: File[]) => {
  // 验证文件数量
  if (uploadQueue.value.length + files.length > props.maxFiles) {
    Message.warning(`最多只能上传 ${props.maxFiles} 个文件`)
    return
  }

  const validFiles = files.filter(file => {
    // 验证文件大小
    if (file.size > props.maxFileSize) {
      Message.warning(`文件 ${file.name} 超过大小限制`)
      return false
    }

    // 验证文件类型
    if (props.accept && !isAcceptedFileType(file)) {
      Message.warning(`不支持的文件类型: ${file.name}`)
      return false
    }

    return true
  })

  validFiles.forEach(file => {
    const queueItem = {
      file,
      name: file.name,
      size: file.size,
      type: getFileType(file),
      status: 'pending' as const,
      progress: 0
    }

    // 生成预览
    if (file.type.startsWith('image/')) {
      generatePreview(file, queueItem)
    }

    uploadQueue.value.push(queueItem)
  })

  emit('files-added', validFiles)
}

const generatePreview = (file: File, queueItem: any) => {
  const reader = new FileReader()
  reader.onload = (e) => {
    queueItem.preview = e.target?.result as string
  }
  reader.readAsDataURL(file)
}

const isAcceptedFileType = (file: File): boolean => {
  if (!props.accept) return true
  const acceptTypes = props.accept.split(',').map(type => type.trim())
  return acceptTypes.some(type => {
    if (type.startsWith('.')) {
      return file.name.toLowerCase().endsWith(type.toLowerCase())
    } else if (type.includes('/*')) {
      return file.type.startsWith(type.replace('/*', ''))
    } else {
      return file.type === type
    }
  })
}

const getFileType = (file: File): string => {
  if (file.type.startsWith('image/')) return 'image'
  if (file.type.startsWith('video/')) return 'video'
  if (file.type.startsWith('audio/')) return 'audio'
  return 'document'
}

const getFileIcon = (type: string) => {
  const icons = {
    image: 'tiny-icon-image',
    video: 'tiny-icon-video',
    audio: 'tiny-icon-music',
    document: 'tiny-icon-file'
  }
  return icons[type] || 'tiny-icon-file'
}

const formatFileSize = (bytes: number): string => {
  const sizes = ['B', 'KB', 'MB', 'GB']
  if (bytes === 0) return '0 B'
  const i = Math.floor(Math.log(bytes) / Math.log(1024))
  return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i]
}

const removeFromQueue = (index: number) => {
  uploadQueue.value.splice(index, 1)
}

const clearQueue = () => {
  uploadQueue.value = uploadQueue.value.filter(item => item.status === 'uploading')
}

const startUpload = async () => {
  if (isUploading.value) return

  isUploading.value = true
  emit('upload-start')

  try {
    for (let i = 0; i < uploadQueue.value.length; i++) {
      const item = uploadQueue.value[i]
      if (item.status !== 'pending') continue

      await uploadSingleFile(item, i)
    }

    const results = uploadQueue.value
      .filter(item => item.status === 'completed')
      .map(item => ({ file: item.file, name: item.name }))

    emit('upload-complete', results)
    Message.success('上传完成')
  } catch (error) {
    emit('upload-error', error as string)
    Message.error('上传失败')
  } finally {
    isUploading.value = false
  }
}

const uploadSingleFile = async (item: any, index: number) => {
  item.status = 'uploading'

  return new Promise<void>((resolve, reject) => {
    // 模拟上传进度
    const interval = setInterval(() => {
      item.progress += Math.random() * 20
      if (item.progress >= 100) {
        item.progress = 100
        item.status = 'completed'
        clearInterval(interval)
        resolve()
      }
    }, 200)

    // 模拟可能的上传失败
    if (Math.random() < 0.1) { // 10% 失败率
      setTimeout(() => {
        clearInterval(interval)
        item.status = 'error'
        item.error = '网络错误'
        reject(new Error('Upload failed'))
      }, 1000)
    }
  })
}

const retryUpload = (index: number) => {
  const item = uploadQueue.value[index]
  item.status = 'pending'
  item.progress = 0
  item.error = undefined
}

// 相机功能
const takePhoto = () => {
  cameraMode.value = 'photo'
  openCamera()
}

const recordVideo = () => {
  cameraMode.value = 'video'
  openCamera()
}

const selectFromGallery = () => {
  selectFiles()
}

const openCamera = async () => {
  try {
    await requestCameraPermission()
    cameraModalVisible.value = true
    await nextTick()
    await startCameraStream()
  } catch (error) {
    Message.error('无法访问相机')
  }
}

const closeCameraModal = () => {
  stopCameraStream()
  cameraModalVisible.value = false
}

const requestCameraPermission = async () => {
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
    throw new Error('设备不支持相机功能')
  }

  // 获取可用的摄像头
  const devices = await navigator.mediaDevices.enumerateDevices()
  cameras.value = devices.filter(device => device.kind === 'videoinput')
}

const startCameraStream = async () => {
  try {
    const constraints = {
      video: {
        deviceId: cameras.value[currentCameraIndex.value]?.deviceId,
        width: { ideal: 1280 },
        height: { ideal: 720 },
        facingMode: currentCameraIndex.value === 0 ? 'user' : 'environment'
      },
      audio: cameraMode.value === 'video'
    }

    cameraStream.value = await navigator.mediaDevices.getUserMedia(constraints)

    if (cameraVideo.value) {
      cameraVideo.value.srcObject = cameraStream.value
      await cameraVideo.value.play()
    }

    // 检查是否支持闪光灯
    const videoTrack = cameraStream.value.getVideoTracks()[0]
    const capabilities = videoTrack.getCapabilities()
    hasFlash.value = 'torch' in capabilities
  } catch (error) {
    console.error('启动相机失败:', error)
    throw error
  }
}

const stopCameraStream = () => {
  if (cameraStream.value) {
    cameraStream.value.getTracks().forEach(track => track.stop())
    cameraStream.value = null
  }

  if (mediaRecorder.value && isRecording.value) {
    mediaRecorder.value.stop()
    isRecording.value = false
  }
}

const switchCamera = async () => {
  if (cameras.value.length <= 1) return

  currentCameraIndex.value = (currentCameraIndex.value + 1) % cameras.value.length
  stopCameraStream()
  await startCameraStream()
}

const toggleFlash = async () => {
  if (!cameraStream.value || !hasFlash.value) return

  const videoTrack = cameraStream.value.getVideoTracks()[0]
  await videoTrack.applyConstraints({
    advanced: [{ torch: !flashEnabled.value }]
  })
  flashEnabled.value = !flashEnabled.value
}

const captureMedia = () => {
  if (cameraMode.value === 'photo') {
    capturePhoto()
  } else {
    if (isRecording.value) {
      stopRecording()
    } else {
      startRecording()
    }
  }
}

const capturePhoto = () => {
  if (!cameraVideo.value || !cameraCanvas.value) return

  const canvas = cameraCanvas.value
  const video = cameraVideo.value

  canvas.width = video.videoWidth
  canvas.height = video.videoHeight

  const ctx = canvas.getContext('2d')
  if (ctx) {
    ctx.drawImage(video, 0, 0)

    canvas.toBlob((blob) => {
      if (blob) {
        const file = new File([blob], `photo_${Date.now()}.jpg`, { type: 'image/jpeg' })
        addFilesToQueue([file])
        closeCameraModal()
        Message.success('照片已添加到上传队列')
      }
    }, 'image/jpeg', uploadSettings.quality)
  }
}

const startRecording = () => {
  if (!cameraStream.value) return

  recordedChunks.value = []

  mediaRecorder.value = new MediaRecorder(cameraStream.value, {
    mimeType: 'video/webm'
  })

  mediaRecorder.value.ondataavailable = (event) => {
    if (event.data.size > 0) {
      recordedChunks.value.push(event.data)
    }
  }

  mediaRecorder.value.onstop = () => {
    const blob = new Blob(recordedChunks.value, { type: 'video/webm' })
    const file = new File([blob], `video_${Date.now()}.webm`, { type: 'video/webm' })
    addFilesToQueue([file])
    Message.success('视频已添加到上传队列')
  }

  mediaRecorder.value.start()
  isRecording.value = true
  recordingStartTime.value = Date.now()
}

const stopRecording = () => {
  if (mediaRecorder.value) {
    mediaRecorder.value.stop()
    isRecording.value = false
  }
  closeCameraModal()
}

// 位置功能
const requestLocation = () => {
  if (uploadSettings.enableGPS && navigator.geolocation) {
    showLocationPrompt.value = true
  }
}

const allowLocation = () => {
  showLocationPrompt.value = false
  navigator.geolocation.getCurrentPosition(
    (position) => {
      Message.success('位置获取成功')
    },
    (error) => {
      Message.warning('位置获取失败')
    }
  )
}

const denyLocation = () => {
  showLocationPrompt.value = false
  uploadSettings.enableGPS = false
}

// 监听GPS设置变化
watch(() => uploadSettings.enableGPS, (enabled) => {
  if (enabled) {
    requestLocation()
  }
})

// 清理资源
onUnmounted(() => {
  stopCameraStream()
})
</script>

<style lang="scss" scoped>
.mobile-uploader {
  .camera-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: $spacing-3;
    margin-bottom: $spacing-4;

    .camera-btn {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: $spacing-2;
      padding: $spacing-4;
      background: rgba(255, 255, 255, 0.8);
      border: 1px solid rgba(255, 255, 255, 0.3);
      border-radius: $radius-xl;
      cursor: pointer;
      transition: all $duration-fast ease;

      &:hover {
        transform: translateY(-2px);
        box-shadow: $shadow-lg;
      }

      &.photo .camera-icon { color: $media-photo; }
      &.video .camera-icon { color: $media-video; }
      &.gallery .camera-icon { color: $media-audio; }

      .camera-icon {
        width: 48px;
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: currentColor;
        border-radius: $radius-full;
        color: white;
        font-size: 20px;
      }

      span {
        font-size: $font-size-sm;
        font-weight: $font-weight-medium;
        color: $gray-700;
      }
    }
  }

  .upload-zone {
    border: 2px dashed rgba($primary-500, 0.3);
    border-radius: $radius-xl;
    padding: $spacing-8;
    text-align: center;
    cursor: pointer;
    transition: all $duration-normal ease;
    background: rgba(255, 255, 255, 0.5);

    &.compact {
      padding: $spacing-4;
      border-radius: $radius-lg;
    }

    &:hover,
    &.drag-over {
      border-color: $primary-500;
      background: rgba($primary-500, 0.05);
      transform: scale(1.02);
    }

    .upload-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: $spacing-3;

      .compact & {
        flex-direction: row;
        gap: $spacing-2;
      }

      .upload-icon {
        font-size: 48px;
        color: $primary-500;

        .compact & {
          font-size: 24px;
        }
      }

      .upload-text {
        .compact & {
          text-align: left;
        }

        .primary-text {
          font-size: $font-size-lg;
          font-weight: $font-weight-medium;
          color: $gray-800;
          margin-bottom: $spacing-1;

          .compact & {
            font-size: $font-size-base;
            margin-bottom: 0;
          }
        }

        .secondary-text {
          font-size: $font-size-sm;
          color: $gray-500;
        }
      }
    }

    .file-input {
      position: absolute;
      opacity: 0;
      pointer-events: none;
    }
  }

  .upload-options {
    background: rgba(255, 255, 255, 0.8);
    border-radius: $radius-lg;
    padding: $spacing-4;
    margin-top: $spacing-4;

    .option-row {
      display: flex;
      gap: $spacing-3;
      margin-bottom: $spacing-3;

      &:last-child {
        margin-bottom: 0;
      }

      .option-item {
        flex: 1;

        &.full-width {
          flex: none;
          width: 100%;
        }

        label {
          display: block;
          margin-bottom: $spacing-1;
          font-size: $font-size-sm;
          font-weight: $font-weight-medium;
          color: $gray-700;
        }
      }
    }
  }

  .upload-queue {
    margin-top: $spacing-6;

    .queue-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: $spacing-4;

      h4 {
        font-size: $font-size-lg;
        font-weight: $font-weight-semibold;
        color: $gray-800;
        margin: 0;
      }

      .queue-actions {
        display: flex;
        gap: $spacing-2;

        .queue-btn {
          display: flex;
          align-items: center;
          gap: $spacing-1;
          padding: $spacing-2 $spacing-3;
          border: 1px solid $primary-500;
          border-radius: $radius-md;
          font-size: $font-size-sm;
          cursor: pointer;
          transition: all $duration-fast ease;

          &:not(.secondary) {
            background: $primary-500;
            color: white;
          }

          &.secondary {
            background: transparent;
            color: $primary-500;
          }

          &:disabled {
            opacity: 0.5;
            cursor: not-allowed;
          }
        }
      }
    }

    .queue-list {
      display: flex;
      flex-direction: column;
      gap: $spacing-3;

      .queue-item {
        display: flex;
        align-items: center;
        gap: $spacing-3;
        padding: $spacing-3;
        background: rgba(255, 255, 255, 0.8);
        border-radius: $radius-lg;
        transition: all $duration-fast ease;

        &.uploading {
          border-left: 4px solid $info;
        }

        &.completed {
          border-left: 4px solid $success;
        }

        &.error {
          border-left: 4px solid $error;
        }

        .file-preview {
          width: 60px;
          height: 60px;
          border-radius: $radius-md;
          overflow: hidden;
          flex-shrink: 0;

          .preview-image {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }

          .file-icon {
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;

            &.image { background: rgba($media-photo, 0.1); color: $media-photo; }
            &.video { background: rgba($media-video, 0.1); color: $media-video; }
            &.audio { background: rgba($media-audio, 0.1); color: $media-audio; }
            &.document { background: rgba($media-document, 0.1); color: $media-document; }
          }
        }

        .file-info {
          flex: 1;
          min-width: 0;

          .file-name {
            font-weight: $font-weight-medium;
            color: $gray-800;
            margin-bottom: $spacing-1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }

          .file-meta {
            display: flex;
            gap: $spacing-2;
            font-size: $font-size-xs;
            color: $gray-500;
            margin-bottom: $spacing-2;
          }

          .upload-progress {
            display: flex;
            align-items: center;
            gap: $spacing-2;

            .progress-bar {
              flex: 1;
              height: 4px;
              background: rgba(0, 0, 0, 0.1);
              border-radius: $radius-full;
              overflow: hidden;

              .progress-fill {
                height: 100%;
                background: $primary-500;
                transition: width $duration-fast ease;
              }
            }

            .progress-text {
              font-size: $font-size-xs;
              color: $primary-500;
              min-width: 50px;
            }
          }

          .error-message {
            color: $error;
            font-size: $font-size-xs;
          }
        }

        .file-actions {
          .action-btn {
            width: 32px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            border: none;
            border-radius: $radius-full;
            cursor: pointer;
            transition: all $duration-fast ease;

            &.remove {
              background: rgba($error, 0.1);
              color: $error;

              &:hover {
                background: rgba($error, 0.2);
              }
            }

            &.retry {
              background: rgba($warning, 0.1);
              color: $warning;

              &:hover {
                background: rgba($warning, 0.2);
              }
            }
          }

          .success-icon {
            width: 32px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba($success, 0.1);
            color: $success;
            border-radius: $radius-full;
          }
        }
      }
    }

    .overall-progress {
      margin-top: $spacing-4;
      padding: $spacing-3;
      background: rgba(255, 255, 255, 0.8);
      border-radius: $radius-lg;

      .progress-info {
        display: flex;
        justify-content: space-between;
        margin-bottom: $spacing-2;
        font-size: $font-size-sm;
        font-weight: $font-weight-medium;
        color: $gray-700;
      }

      .progress-bar {
        height: 8px;
        background: rgba(0, 0, 0, 0.1);
        border-radius: $radius-full;
        overflow: hidden;

        .progress-fill {
          height: 100%;
          background: $gradient-primary;
          transition: width $duration-fast ease;
        }
      }
    }
  }

  .camera-modal {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.9);
    z-index: $z-index-modal;
    display: flex;
    align-items: center;
    justify-content: center;

    .camera-container {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      background: black;

      .camera-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: env(safe-area-inset-top) $spacing-4 $spacing-3;
        background: rgba(0, 0, 0, 0.8);
        color: white;

        h3 {
          font-size: $font-size-lg;
          margin: 0;
        }

        .close-btn {
          width: 44px;
          height: 44px;
          background: transparent;
          border: none;
          color: white;
          font-size: 20px;
          cursor: pointer;
        }
      }

      .camera-viewport {
        flex: 1;
        position: relative;
        overflow: hidden;

        .camera-stream {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }

        .camera-canvas {
          position: absolute;
          top: 0;
          left: 0;
        }
      }

      .camera-controls {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: $spacing-6 $spacing-4 calc(env(safe-area-inset-bottom) + #{$spacing-6});
        background: rgba(0, 0, 0, 0.8);

        .control-btn {
          width: 48px;
          height: 48px;
          background: rgba(255, 255, 255, 0.2);
          border: none;
          border-radius: $radius-full;
          color: white;
          font-size: 20px;
          cursor: pointer;
          transition: all $duration-fast ease;

          &:hover {
            background: rgba(255, 255, 255, 0.3);
          }

          &.active {
            background: $warning;
          }
        }

        .capture-btn {
          width: 80px;
          height: 80px;
          background: transparent;
          border: 4px solid white;
          border-radius: $radius-full;
          cursor: pointer;
          transition: all $duration-fast ease;
          position: relative;

          &.recording {
            border-color: $error;

            .capture-inner {
              background: $error;
              border-radius: $radius-sm;
            }
          }

          .capture-inner {
            width: 100%;
            height: 100%;
            background: white;
            border-radius: $radius-full;
            transition: all $duration-fast ease;
          }

          &:active {
            transform: scale(0.9);
          }
        }
      }
    }
  }

  .location-prompt {
    position: fixed;
    top: 120px;
    left: $spacing-4;
    right: $spacing-4;
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(20px);
    border-radius: $radius-lg;
    padding: $spacing-4;
    z-index: $z-index-toast;
    box-shadow: $shadow-lg;

    .prompt-content {
      display: flex;
      align-items: center;
      gap: $spacing-2;
      margin-bottom: $spacing-3;
      font-size: $font-size-sm;
      color: $gray-700;
    }

    .prompt-actions {
      display: flex;
      gap: $spacing-2;
      justify-content: flex-end;

      button {
        padding: $spacing-2 $spacing-4;
        border: 1px solid $gray-300;
        border-radius: $radius-md;
        background: transparent;
        color: $gray-600;
        font-size: $font-size-sm;
        cursor: pointer;
        transition: all $duration-fast ease;

        &.primary {
          background: $primary-500;
          border-color: $primary-500;
          color: white;
        }
      }
    }
  }
}

// 过渡效果
.modal-enter-active,
.modal-leave-active {
  transition: opacity $duration-normal ease;
}

.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

.toast-enter-active,
.toast-leave-active {
  transition: all $duration-normal ease;
}

.toast-enter-from,
.toast-leave-to {
  opacity: 0;
  transform: translateY(-20px);
}

// 暗色主题
[data-theme="dark"] {
  .mobile-uploader {
    .camera-btn {
      background: rgba(255, 255, 255, 0.1);
      border-color: rgba(255, 255, 255, 0.1);

      span {
        color: $gray-300;
      }
    }

    .upload-zone {
      background: rgba(255, 255, 255, 0.05);
      border-color: rgba($primary-500, 0.5);

      .upload-text .primary-text {
        color: $gray-200;
      }
    }

    .upload-options,
    .queue-item {
      background: rgba(255, 255, 255, 0.05);
    }

    .location-prompt {
      background: rgba(0, 0, 0, 0.9);

      .prompt-content {
        color: $gray-300;
      }
    }
  }
}
</style>
